#include "FDEBCompatibility.h"

// 角度相似度
double angleCompatibility(const FDEBEdge& e1, const FDEBEdge& e2) {
    Vector2D v1 = vector(e1.source, e1.target);
    Vector2D v2 = vector(e2.source, e2.target);
    return std::abs(dotProduct(normalize(v1), normalize(v2)));
}

// 长度相似度
double scaleCompatibility(const FDEBEdge& e1, const FDEBEdge& e2) {
    double l1 = distance(e1.source, e1.target);
    double l2 = distance(e2.source, e2.target);
    return 2.0 / (l1 / l2 + l2 / l1);
}

// 位置相似度
double positionCompatibility(const FDEBEdge& e1, const FDEBEdge& e2) {
    FPoint m1 = midpoint(e1.source, e1.target);
    FPoint m2 = midpoint(e2.source, e2.target);
    double l1 = distance(e1.source, e1.target);
    double l2 = distance(e2.source, e2.target);
    double minL = std::min(l1, l2);
    double dist = distance(m1, m2);
    return 2.0 / (dist / minL + minL / dist);
}

// 可见相似度
double visibilityCompatibility(const FDEBEdge& e1, const FDEBEdge& e2) {
    FPoint I0 = projectPointOnEdge(midpoint(e2.source, e2.target), e1);
    FPoint I1 = projectPointOnEdge(midpoint(e1.source, e1.target), e2);

    FPoint mid1 = midpoint(e1.source, e1.target);
    FPoint mid2 = midpoint(e2.source, e2.target);

    double d = distance(mid1, mid2);
    if (d == 0.0) return 0.0;

    return std::max(0.0, 1.0 - (distance(I0, mid1) + distance(I1, mid2)) / d);
}

// 投影点到边上
FPoint projectPointOnEdge(const FPoint& p, const FDEBEdge& edge) {
    FPoint a = edge.source;
    FPoint b = edge.target;
    Vector2D ab = vector(a, b);
    Vector2D ap = vector(a, p);
    double ab_dot = dotProduct(ab, ab);
    if (ab_dot == 0.0) return a;  // source == target
    double t = dotProduct(ap, ab) / ab_dot;
    double clampedT = std::max(0.0, std::min(1.0, t));
    return interpolate(a, b, clampedT);
}

// 总相似度
double calculateCompatibility(const FDEBEdge& e1, const FDEBEdge& e2) {
    return angleCompatibility(e1, e2)
         * scaleCompatibility(e1, e2)
         * positionCompatibility(e1, e2)
         * visibilityCompatibility(e1, e2);
}
